﻿namespace Ngs.Data
{
    using System;
    using System.Reflection;

    public abstract class AssociationMapper<TSource, TDestination, TSubSource, TSubDestination> : Mapper<TSource, TDestination>, IAssociationMapper<TSource, TDestination, TSubSource, TSubDestination>
    {
        protected AssociationMapper()
        {
            FactoryMethod = () => Activator.CreateInstance<TSubDestination>();
        }

        #region Properties

        public Func<TSubDestination> FactoryMethod { get; set; }

        public MemberInfo Member { get; set; }

        public Action<TSubSource, TSubDestination> ReferenceMap { get; set; }
        #endregion

        public Mapper<TSource, TDestination> MapReference(Action<TSubSource, TSubDestination> reference)
        {
            ExceptionFactory.ThrowIfArgumentNull(reference);
            this.ReferenceMap += reference;
            return this;
        }

        public Mapper<TSource, TDestination> SubDestinationFactory(Func<TSubDestination> factory)
        {
            ExceptionFactory.ThrowIfArgumentNull(factory);
            this.FactoryMethod = factory;
            return this;
        }

        public sealed override void Execute(TSource entity, TDestination obj)
        {
            base.Execute(entity, obj);
            ExecuteCore(entity, obj);
        }

        protected abstract void ExecuteCore(TSource entity, TDestination obj);
    }
}
